home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
OPTANS10.ARJ
/
OPTANSI.DOC
< prev
next >
Wrap
Text File
|
1992-06-14
|
60KB
|
1,295 lines
*******************************************************************************
OptANSI Library
version 1.0
Copyright 1992 Michael Dannov
Optimizing ANSI Output Library for Borland C
*******************************************************************************
DOCUMENTATION
------------------------------------------------------------------------------
*ABOUT OPTANSI*
What is the OptANSI Library?
OptANSI was designed to output fully optimized and compressed ANSI codes
on the fly to any ANSI interpreting device. It is NOT an interpreter by any
means, so it does not receive incoming ANSI and convert it into logical screen
output. Usually this control is left to the ANSI device or the comm program.
Who can use the OptANSI Library?
Anyone who programs in Borland C and has need to use the ANSI screen
interface can use OptANSI. It is well suited for most communication appli-
cations like BBS programs, remote doorways, fossil drivers, telecommunication
programs, and BBS doors. It can also be used with ANSI drawing packages and
other ANSI utilities. In fact, it has been used to design the popular AOPT
(ANSI Optimizer) utility which takes standard .ANS files and reduces them to
their minimum size without affecting resulting output. You may also find other
uses for OptANSI if you simply want an alternative method for screen output
aside from VIDEO BIOS, direct screen, or DOS calls. All OptANSI functions can
be piped through DOS if you use standard printf() and other DOS forwarding
calls, thereby allowing you to send screen locations and color codes to the
screen or to a file. This is especially useful if standard conio is not always
appropriate or compatible; for instance, DOS shells using telecommunications
without a gateway.
Why use the OptANSI Library, say as opposed to another?
There are a number of generic ANSI libraries out there to use. I might
have used them myself if I hadn't grown so critical of all the wasted time
sending unnecessary codes. ANSI is a slow interface by design and there is
little sense wasting good process time on unneeded output. For instance, say
you are using your 2400 baud modem online with a BBS who's sysop loves
switching between those ANSI colors. It takes a lot of time to draw the screen
at that speed and any sort of optimization at all could be beneficial. OptANSI
will practically never result in slower output even if your application uses
14400 baud transfers. OptANSI should not impede output times; it can only
benefit them.
OptANSI functions will produce output that is 10-30% smaller of all
output sent (ie, ANSI and all other text) compared with other libraries. Of
pure ANSI output, OptANSI produces 20-60% smaller output. Both these figures
are dependant on how intensive your the of ANSI.
Another important feature is that OptANSI has ten times the number of
functions as other libraries. It's true, many of these are macros that call
coded functions, but the underlying code and data (if ALL functions in the
library are used) occupies less than 1.5K of memory.
How can I use OptANSI Library?
First, link the OptANSI LIBrary file to your project. Second, all OptANSI
functions are very similar to conio functions, so it shouldn't be to much of
a strain to learn and use. The function names use a one letter suffix "a" for
ANSI. An example is gotoxy(x, y) which in OptANSI is agotoxy(x, y, &x, &y).
OptANSI functions are very tight. Much of the code is written in assembly
using optimized BC asm inlines. Also, the library is spread out so that only
functions called by your program are actually linked into the executable.
How does OptANSI work?
OptANSI, unlike rival libraries, remembers critical information about its
former states, like last cursor position and previous color. OptANSI takes
advantage of all the ASCII and ANSI rules to take advantage of all possible
shortcuts and will 99.9% of the time find the shortest output path.
There seem to be a number of ANSI standards; by which one does OptANSI comply?
OptANSI is mostly composed of a combination of the shared rules of many
different ANSI devices or at least their expected operations. There have been
bugs in various ANSI drivers released over the last 10 years. ANSI.SYS which
accompanies DOS is no exception. OptANSI has been tested with most public ANSI
drivers and certain flags have been implemented to allow the programmer or the
user (if designed to do so) to decide which outputs are valid to optimize.
OptANSI also includes a number of functions that the programmer can
decide whether or not to implement. Some of the NANSI (New ANSI) and other
ANSI extensions have been included like insert line, delete line, insert
spaces, delete spaces, etc.
Performance Results from ALL output sent:
Raw OptANSI Other libraries FNs
WWIV BBS Capture (*): 69180 56241 - 19% 70683 + 2% 1
PCBoard Capture (*): 41335 39374 - 5% 47763 + 15% 1
Wildcat (*): 26639 19665 - 26% 27213 + 2% 1,2
Doorway, Rmt DOS Capture: 51308 42610 - 17% 55389 + 8% 2,1
TheDraw ANSI: 24271 23521 - 3% 28253 + 16% 2,1
Raw - Raw Output
OptANSI - Raw Output retransmit through OptANSI
Other Libraries - Raw Output retransmit through other libraries
FNs - Primary ANSI functions were (in order of probability):
1 - Color Functions
2 - Location Functions
3 - Miscellaneous Functions
(*) Results from BBS Systems are based on ANSI captures during a regular
session with ANSI on. This includes newscanning files (FN 1), reading a
message (FN1), writing a single reply with a full screen editor if available
(FN 1,2), etc.
PCBoard's ANSI is pretty well optimized.
NOTE: The values above are probably not reflective of performance for your
applications since many of the above programs have already been optimized,
which goes to prove that it is probably a good idea.
------------------------------------------------------------------------------
*REGISTERING OPTANSI*
As a registered owner of the OptANSI library, you will get complete
source code to the library. You can modify the source code to fit your needs
if necessary, but you can never give out the OptANSI based source code even if
it is modified beyond recognition. You also may not use the OptANSI library to
make a competing library. Ergo, you cannot use OptANSI to make an optimizing
ansi library that you distribute or sell to others, not even for other
platforms [unless you get written permission from the author]. Also, there
exists a copyright notice in the data of ainit. This does not need to be
displayed anywhere in your programs, but must remain in the final executable.
Do not remove this code from ainit.c. Other restrictions apply based on which
license you pay. See below.
No Royalties Apply to OptANSI library licenses. However, different
licenses have different prices. Please read the information about each license
option below to ensure that one you select is the one that satisfies your
qualifications. Limitations apply to each. If you have questions or require
special considerations, please contact the author listed below.
-LICENSE OPTION------------------------------------ -REG PRICE-
Private license $15
Shareware license $30
Small commercial license $50
Full commercial license $500
Printed documentation ADD $10
All Future Upgrades $5
Private License: OptANSI library can only be included in software written
which is NOT FOR SALE. Ie, it is part of your cost for doing business. One
license applies to one person or one business depending on the licensee's
name. Subcontractors or other developers must license one OptANSI library for
each individual or company that he programs for that requires OptANSI. Markup
in such cases may apply but is only appropriate up to 33%.
Shareware license: OptANSI library can only be included in software written
which are for sales in the shareware market only. One license applies to all
shareware products written by the same licensed author or business.
[Shareware courtesy.]
Small commercial license: OptANSI library can be included in software written
which is for sale commercially, but is limited to only those applications
whose primary sales comes from direct sale to a customer and not through a
retailer. One license is necessary for each separate software package (of a
different name) that you sell which uses OptANSI functions.
Full commercial license: OptANSI library can be included in software written
for any commercial sales. This includes products which are resold or sold at
software stores. One license is necessary for each software package (of a
different name) that you sell which uses OptANSI functions.
The prices above are very small representations of actual development
costs in each scenario; especially considering the hundreds of hours you would
need to develop the equivalent of OptANSI. Special considerations will be
considered if prices are unrealistic for your purpose. If you need more
licensing freedom, contact the author at an address listed below.
*ADDRESS* *HOME BBS* -> email Michael Dannov
Michael Dannov Programmer Tech Industries
18102 Brookhurst ST, Ste M Box #176 714-220-1561
Fountain Valley, CA 92708 PCBoard/Qmail, 14400 HST, 24hrs
(General/Programming)
------------------------------------------------------------------------------
*INFORMATION ABOUT ANSI*
ANSI is a useful extension to standard output which normally behaves like
teletype. Teletype output cannot change screen colors or access all the
different locations on the screen. It can only write text data, moving down
and to the right on the screen. ANSI extensions break this barrier and add
these functions. It works by sending a special sequence of characters (below)
which tell the interpreter what to do.
ESC [ Num ; .. Cmd
ESC is the character 27
Num is a number value in text format like "15"
Cmd is a command character which identifies how to behave
; separates multiple number parameters
To use ANSI from DOS, you must use some form of ANSI emulator. One
accompanies DOS called ANSI.SYS. If you place DEVICE=ANSI.SYS in your
CONFIG.SYS, ANSI will be installed. Other authors have put other versions of
ANSI into the mainstream. They include FANSI, NANSI, DEVSYS, etc. PC Magazine
has also released a memory resident version of ANSI (with some PCBoard
extensions) which can be placed in your AUTOEXEC.BAT instead of CONFIG.SYS.
Also, some manufacturers of video cards have offered replacement ANSI.SYS
files on their resource disks. In my experience, these versions of ANSI have
been the most incompatible with ANSI rules. If asked to recommend a best ANSI
for all needs, I would probably have to suggest a version of NANSI because it
adds many useful extensions and is 3 times faster than DOS' ANSI.
To use ANSI from a telecommunications program or other program, make sure
to turn ANSI emulation on. NOTE to programmers writing applications for
telecommunications: QMODEM has one inconsistency with ansi colors. Make sure
to explain to QModem users that they should turn on Strict Colors in the
Video|Toggles menu of the options screen, or else they risk reset colors not
being right.
*OPTANSI BASICS*
To use OptANSI, include OPTANSI.H at the top of your program. This header
includes many shortcut macros and defines all the OptANSI function prototypes.
OptANSI's functions return a pointer to an ANSI string (char *) back to
the main function instead of using hardcoded output resources. This allows
programmers to use their own string output functions. This is especially
critical if you're going to be using telecommunications or other output
routines without a fossil driver.
Most OptANSI functions share a 15 char buffer area used in the creation
of ANSI output strings. This is more than enough for an optimized ANSI string.
However, you must note that this does place a constraint on OptANSI use. Every
OptANSI function needs to be called on a separate line. Ie, you cannot pass
multiple OptANSI functions through the same output function.
This is invalid:
printf("%s%sHi", acolor(31), agotoxy(25, 10, &x, &y));
This is better:
printf(acolor(31));
printf(agotoxy(25, 10, &x, &y));
printf("Hi");
Make sure to send OptANSI functions on separate lines. Even though the
last 2 lines could have been combined as printf("%sHi", agotoxy(...)); it is
better to get into the practice of keeping them on separate lines.
Another solution exists that allows you to use OptANSI function names
instead of each time passing them through an output function like printf(). To
use this option, include AUSER.H after OPTANSI.H. This file is filled with
useful macros which expand OptANSI function names into full expressions using
an output function of your choice. For instance, instead of:
printf(agotoxy(1, 1, &x, &y));
you could put:
agotoxy(1, 1, &x, &y);
because AUSER.H defines:
#define aout(s) printf(s) // This macro you can define to your reqs
#define agotoxy(x, y, ox, oy) aout(agotoxy(x, y, ox, oy))
This is a useful shortcut and the recommended means of operation because
it treats each OptANSI function like already familiar conio functions, and
because it automatically ensures that each function is called on its own
separate line, resolving the above dilemma.
NOTE ABOUT USING printf and other text output functions:
There is one problem with using functions like printf or other output
functions. There is a problem because these output routines do not keep store
a variable that keeps track of the current x and y cursor coordinates and
OptANSI location functions need to know this information in order to optimize
new points. It is therefore recommended that if you are writing your own
output routines that you make your functions know their current screen
positions. If you use the likes of printf or other text output functions, you
might need to update x & y by using wherex() and wherey() before using
location functions. It is your responsibility that these variables stay
accurate. See location functions for more information.
Because some ANSI emulators behave differently than others in some
respects, a set of flags have been assigned to allow you to determine how some
optimizations behave. This char variable is called ashortcuts. It's purpose
is to determine if some sequence of characters does not behave like expected.
These optimization are labeled in OPTANSI.H as:
1 aBKSP Set if backspace (char 8, ^H) is nondestructive.
2 aLF Set if linefeed (char 10, ^J) moves cursor down only, if
false, assumes LF is equivalent to CR/LF combination.
4 aCR Set if carriage return (char 13, ^M) moves the cursor to
left margin of the same line only.
8 aCLRSCR Set if clear screen (char 12, ^L) clears the entire screen
to the current color. Telix requires this on.
64 aRESET Set if reset color (ESC[m) resets the color to lightgray on
black (7), almost always true. See ashorttelecom() notes.
128 aNANSI Set if you want to use NANSI or FANSI extensions. See
Compilation Notes for more information on this flag.
Two macros are defined in OPTANSI.H to help assign ashortcuts a proper
value. Example usage is below:
ashort(aBKSP | aCR | aRESET); // This will turn on BKSP, CR, and RESET
// and set ashortcuts=69
or you could say:
anotshort(aLF | aCLRSCR | aNANSI); // Will set all flags on except aLF,
// aCLRSCR, and aNANSI
Depending on the output device you send these controls to, these general
rules apply and these macros can be used:
ashortdos()
for printf() & other dos output functions: (ashortcuts defaults to this mode)
aBKSP | aCR | !aLF | !aCLRSCR | aRESET
ashorttelecom()
telecommunications:
!aBKSP | aCR | aLF | aCLRSCR | aRESET
- In some telecom progs, backspace can be set to nondestructive, it is
best to assume this is not true and use !aBKSP and be sure
- In QModem, if Strict Colors is on, use aRESET, else !aRESET
- CR/LF modes are usually turned off
- Telix should have aCLRSCR true, otherwise it will not clear the
screen to the current color.
There are three parts to the OptANSI function library. The first is
miscellaneous color functions. The second is color functions. And the last is
location functions.
*MISCELLANEOUS FUNCTIONS*
#########
# ainit # Initialize OptANSI functions, variables
#########
Declaration: int ainit() function
Remark: ainit is not necessary to be called to use OptANSI functions. Its only
purpose is to define OptANSI global variables. It may be good practice to
include it at the top of your program in case of future versions require it.
########
# acmd # Return an ANSI string based on parameters
########
Declaration: char *acmd(char num, char cmd) function
Remark: Returns an ANSI string in the form: ESC [ num cmd. Num is expanded
into a string. This function operates as a universal for common ANSI
expressions. If num is 0 or 1, num will not expanded. To force 1 to be
expanded, use instead the macro SP_ONE, like acmd(SP_ONE, 'K').
NOTE: Be careful - If you use this command to change colors or move on the
screen manually, you MUST update the global variables corresponding to the
command.
Example:
acmd(2, 'J'); // Sends ESC[2J which clears the screen
axpos=1; // Must update axpos & aypos
aypos=1;
#########
# atest # Send ANSI test presence string, Request cursor location
#########
Declaration: char *atest() function
Remark: Returns the ANSI request string. If ANSI is present, the ANSI emulator
will send back a standardized string. If atest is sent to standard output
(printf or equivalent), it will put this response string in the keyboard
buffer. See awherexy() and aresult() for logical next step.
##########
# atest1 # Flush Standard input buffer then Send ANSI test presence string,
########## Request cursor location.
Declaration: char *atest1() function
Remark: Same as atest above except that it is specialized for standard io.
This way the keyboard buffer will be cleared to eliminate any possibility of
error. See awherexy() and aresult1() for logical next step.
###########
# aresult # Test atest response string
###########
Declaration: int aresult(char *str) function
Remark: Compare str to expected result string. If true, it returns 1,
otherwise 0 for false. The aresult() function should follow atest().
Example:
char s[15];
atest();
readbuf(&s); // reads input buffer until enter
if (aresult(s)) {
...
} else
printf("ANSI Not Available");
############
# aresult1 # Read keyboard buffer and tests atest response string
############
Declaration: int aresult1() function
Remark: This function is similar to aresult except that it is specialized for
standard io. It does not need an outside function to read in the atest result
string. It will read the keyboard buffer for you. It then compares this string
to that expected response. If true, it returns 1, otherwise 0 for false. The
aresult1() function should follow atest1().
Example:
atest1();
if (aresult1()) {
...
} else
printf("ANSI Not Available");
############
# aresult2 # Test interrupts for presence of ANSI
############
Declaration: int aresult2() function
Remark: This function is similar to aresult except that it tests the computer
interrupts directly. It does not require atest to determine if ANSI is
present. If ANSI is present, it returns 1, otherwise 0 for false.
NOTE: This function is only available for DOS 4.0+ ANSI.SYS. Most 3rd party
ANSI drivers include this installation test.
Example:
if (aresult2()) {
...
} else
printf("ANSI Not Available");
#############
# aupdatexy # Update axpos and aypos to current locations on screen
#############
Declaration: aupdatexy() macro-> calls wherex, wherey
Remark: This function is useful in keeping axpos and aypos equal to the
current cursor coordinates. It is necessary to call before OptANSI location
functions if you don't have an output routine that calculates axpos and aypos
as it outputs. However, This function is only useful locally and not for
telecommunications. For telecommunications, the output function should
calculate x and y positions automatically.
Example:
printf("This is a test\n"); // axpos & aypos isn't updated
aupdatexy(); // This updates axpos and aypos
agotoxy(5, 1); // Now, this will work
##############
# aupdatexy1 # Update axpos and aypos to current locations on screen
##############
Declaration: aupdatexy1() macro-> points to low mem
Remark: This function is the same as aupdatexy() above except that instead of
calling the interrupts, it points to low memory where x and y cursor positions
for page 0 are stored (x-0:450, y-0:451). Use this only if you are positive
that these low memory positions are reliable measures of x and y.
###########
# aclrscr # Clears the screen and homes the cursor
###########
Declaration: char *aclrscr() function
Remark: Returns an optimized ANSI string that will clear the screen and home
the cursor, axpos=1 and aypos=1, usually clears the screen to the current
color. See location functions. Equivalent to conio's clrscr() function. Telix
requires ashortcuts aCLRSCR to be true because ANSI's ESC sequence will clear
the screen to the default terminal color.
###########
# aclreol # Clears the line from the cursor to the end of the line
###########
Declaration: char *aclreol() function
Remark: Returns an ANSI string that will clear the line from the current
cursor position to the end of the line, usually clears to the current color.
Equivalent to conio's clreol() function. Telix clears to the default terminal
color.
----------------
The functions below are within ANSI specifications but for some reason
very rarely implemented. It is therefore recommended that they not be used
unless you can ensure that they will work on your intended platform.
Some of the result possibilities are listed below in the windows. Six
emulators have been tested. Assume the most recent versions of each. You may
have to test others if they are not listed. Note carefully that some emulators
will clear or move the cursor and others will not.
###########
# aclrbol # Clear line from cursor to beginning of line
###########
Declaration: char *aclrbol() macro-> calls acmd
Remark: Returns an ANSI string that will clear the line from the current
cursor position to the beginning of the line. This function is rarely
supported by ANSI emulators. Different behaviors are listed below:
┌──────────────┬──────┬─────────────────────────────────────────────┐
│Misc Function │Interp│Behavior │
├──────────────┼──────┼─────────────────────────────────────────────┤
│ │ANSI │None │
│ ClrBol │NANSI │Same as clreol │
│ │FANSI │Clears left of cursor to beginning of line │
│ ESC[1K │QMODEM│Same as clreol │
│ │PCPLUS│Clears cursor and left to beginning of line │
│ │TELIX │Clears cursor and left to beginning of line │
└──────────────┴──────┴─────────────────────────────────────────────┘
############
# aclrline # Clears entire line
############
Declaration: char *aclrline() macro-> calls acmd
Remark: Returns an ANSI string that will clear the entire line, but not delete
the line, cursor does not move. This function is rarely supported by ANSI
emulators. Different behaviors are listed below:
┌──────────────┬──────┬─────────────────────────────────────────────┐
│Misc Function │Interp│Behavior │
├──────────────┼──────┼─────────────────────────────────────────────┤
│ │ANSI │None │
│ ClrLine │NANSI │Same as clreol │
│ │FANSI │Clears entire line, moves cursor to x=1 │
│ ESC[2K │QMODEM│Same as clreol │
│ │PCPLUS│Clears entire line, moves cursor to x=1, BUG │ **
│ │TELIX │Clears entire line │
└──────────────┴──────┴─────────────────────────────────────────────┘
- Procomm Plus has a bug with this function. The cursor stays at the same
position, but its internal value for the x position is set to 1, so as
soon as a character is sent, it is displayed at the old cursor position,
and then moves the cursor to position 2 on the same line.
################
# aclrscrabove # Clears screen above and left of cursor position
################
Declaration: char *aclrscrabove() macro-> calls acmd
Remark: Returns an ANSI string that will clear the entire screen above and
left of the cursor, cursor does not move. This function is rarely supported by
ANSI emulators. Different behaviors are listed below:
┌──────────────┬──────┬─────────────────────────────────────────────┐
│Misc Function │Interp│Behavior │
├──────────────┼──────┼─────────────────────────────────────────────┤
│ │ANSI │Same as clrscr │
│ ClrScrAbove │NANSI │Clears everything above and left of cursor │
│ │FANSI │Clears everything above and left of cursor │
│ ESC[1J │QMODEM│Clears cursor and everything above and left │
│ │PCPLUS│Clears cursor and everything above and left │
│ │TELIX │Clears cursor and everything above and left │
└──────────────┴──────┴─────────────────────────────────────────────┘
################
# aclrscrbelow # Clears screen below and right of cursor position
################
Declaration: char *aclrscrbelow() macro-> calls acmd
Remark: Returns an ANSI string that will clear the entire screen below and
right of the cursor, cursor does not move. This function is rarely supported
by ANSI emulators. Different behaviors are listed below:
┌──────────────┬──────┬─────────────────────────────────────────────┐
│Misc Function │Interp│Behavior │
├──────────────┼──────┼─────────────────────────────────────────────┤
│ │ANSI │Same as clrscr │
│ ClrScrBelow │NANSI │Clears cursor and everything below and right │
│ │FANSI │Clears cursor and everything below and right │
│ ESC[J │QMODEM│Clears cursor and everything below and right │
│ │PCPLUS│Clears cursor and everything below and right │
│ │TELIX │Clears cursor and everything below and right │
└──────────────┴──────┴─────────────────────────────────────────────┘
############
# ainsline # Insert a line before the current line
############
Declaration: char *ainsline(char y) macro-> calls acmd
Remark: Returns an ANSI string that inserts y lines before the current line.
Different behaviors are listed below:
┌──────────────┬──────┬─────────────────────────────────────────────┐
│Misc Function │Interp│Behavior │
├──────────────┼──────┼─────────────────────────────────────────────┤
│ │ANSI │Displays L │
│ InsertLine │NANSI │Inserts # lines starting at the current line │
│ │FANSI │Rotates entire current line down # lines │
│ ESC[#L │QMODEM│None │
│ │PCPLUS│Inserts # lines starting at the current line │
│ │TELIX │Inserts # lines starting at the current line │
└──────────────┴──────┴─────────────────────────────────────────────┘
############
# adelline # Delete lines starting at current
############
Declaration: char *adelline(char y) macro-> calls acmd
Remark: Returns an ANSI string that deletes y lines starting at the current
line. Different behaviors are listed below:
┌──────────────┬──────┬─────────────────────────────────────────────┐
│Misc Function │Interp│Behavior │
├──────────────┼──────┼─────────────────────────────────────────────┤
│ │ANSI │Displays M │
│ DeleteLine │NANSI │Deletes # lines starting at the current line │
│ │FANSI │Deletes # lines starting at the current line │
│ ESC[#M │QMODEM│Freeze Input until ESC pressed │
│ │PCPLUS│Freeze Input until ESC pressed │
│ │TELIX │Deletes # lines starting at the current line │
└──────────────┴──────┴─────────────────────────────────────────────┘
############
# ainschar # Insert chars starting at cursor
############
Declaration: char *ainschar(char x) macro-> calls acmd
Remark: Returns an ANSI string that inserts x spaces starting from the cursor
position. Characters that go past the right margin are deleted. Different
behaviors are listed below:
┌──────────────┬──────┬─────────────────────────────────────────────┐
│Misc Function │Interp│Behavior │
├──────────────┼──────┼─────────────────────────────────────────────┤
│ │ANSI │Displays @ │
│ InsertChars │NANSI │Inserts # spaces starting at cursor │
│ │FANSI │Inserts # spaces starting at cursor │
│ ESC[#@ │QMODEM│Displays ESC sequence │
│ │PCPLUS│Inserts # spaces starting at cursor │
│ │TELIX │Inserts # spaces starting at cursor │
└──────────────┴──────┴─────────────────────────────────────────────┘
############
# adelchar # Deletes characters starting at cursor
############
Declaration: char *adelchar(char x) macro-> calls acmd
Remark: Returns an ANSI string that deletes x characters starting at the
cursor. Different behaviors are listed below:
┌──────────────┬──────┬─────────────────────────────────────────────┐
│Misc Function │Interp│Behavior │
├──────────────┼──────┼─────────────────────────────────────────────┤
│ │ANSI │Displays P │
│ DeleteChar │NANSI │Deletes # characters starting at cursor │
│ │FANSI │Deletes # characters starting at cursor │
│ ESC[#P │QMODEM│Displays ESC sequence │
│ │PCPLUS│Deletes # characters starting at cursor │
│ │TELIX │Deletes # characters starting at cursor │
└──────────────┴──────┴─────────────────────────────────────────────┘
*COLOR FUNCTIONS*
The color functions define acurattr a char. This variable is updated to
reflect the current color after each OptANSI color function. If you change the
current color by other means, you will need to update acurcolor on your own.
If you do not, optimizations will make improper assumptions and actual
resulting colors might not match desired.
All functions will only return an ANSI string when necessary. Changing
the current color to the same color value that acurattr already holds will
send back a null string.
These color values are defined by OPTANSI.H or CONIO.H:
0 BLACK dark colors
1 BLUE
2 GREEN
3 CYAN
4 RED
5 MAGENTA
6 BROWN
7 LIGHTGRAY
8 DARKGRAY light colors
9 LIGHTBLUE
10 LIGHTGREEN
11 LIGHTCYAN
12 LIGHTRED
13 LIGHTMAGENTA
14 YELLOW
15 WHITE
8 HIGHLIGHT add to first 0-7 only
128 BLINK add to full color attributes only
########
# ATTR # Calculate color from foreground and background values
########
Declaration: char ATTR(char fr, char bk) macro (math)
Remark: This macro returns a character value, calculated from foreground and
background values (0-15 each) and expands it into a full 8 bit color
attribute.
If you want to use the BLINK macro with ATTR, use it after ATTR:
ATTR(fr, bk)+BLINK
Example:
i=ATTR(WHITE /*15*/, BLUE /*1*/); -> returns value 31
#####################
# acolor, atextattr # *Change current color/attribute
#####################
Declaration: char *acolor(char nc) function
char *atextattr(char nc) macro-> calls acolor
Remark: Returns an optimized ANSI string that will change the active color,
acurattr is also set to nc. Equivalent to conio's textattr(). Full foreground,
background, highlight, and blink bits can be modified. Acceptable values for
nc are 0-255. See ATTR() for quick method of calculating colors.
* This is the recommended method of changing colors.
###############
# aforcecolor # Forces color to new color value ignoring optimizations
###############
Declaration: char *aforcecolor(char nc) macro-> calls acolor
Remark: Returns a full ANSI string that will change the current active color,
accurattr is also set to nc. This function is like acolor except that it will
send the complete ANSI string as if the color was reinitialized, ie it ignores
last acurattr value when returning changing the color. For instance, lets say
that you are worried about line noise through the modem and acurattr possibly
becomes obscured, aforcecolor(7) would ensure that color 7 is set by ignoring
internal optimizations.
##############
# atextcolor # Change current foreground color
##############
Declaration: char *atextcolor(char nf) macro-> calls acolor
Remark: Returns an optimized ANSI string that will change the active fore-
ground color, only the first four bits of acurattr are updated. Equivalent to
conio's textcolor(). Foreground and highlight bits can be modified. Acceptable
values for nf are 0-15. Larger values can result in unexpected colors.
###################
# atextbackground # Change current background color
###################
Declaration: char *atextbackground(char nb) macro-> calls acolor
Remark: Returns an optimized ANSI string that will change the active back-
ground color, only the last four bits of acurattr are updated. Equivalent to
conio's textbackground(). Background and blink bits can be modified.
Acceptable values for nb are 0-15. Larger values can result in unexpected
colors.
##########################
# ahighlight, ahighvideo # Set highlight bit of current color
##########################
Declaration: char *ahighlight() function
char *ahighvideo() macro-> calls ahighlight
Remark: Returns an optimized ANSI string that will turn highlight on, only the
highlight bit 4 of acurattr is updated. Equivalent to conio's highvideo().
############################
# anohighlight, alowvideo, # Clear highlight bit of current color
# anormvideo, adim #
############################
Declaration: char *anohighlight() macro-> calls acolor
char *alowvideo() macro-> calls anohighlight
char *anormvideo() macro-> calls anohighlight
char *adim() macro-> calls acolor
Remark: Returns an optimized ANSI string that will turn highlight off, only
the highlight bit (4) of acurattr is updated. Equivalent to conio's lowvideo()
and normvideo().
##########
# ablink # Set blink bit of current color
##########
Declaration: char *ablink() function
Remark: Returns an optimized ANSI string that will turn blink on, only the
blink bit (8) of acurattr is updated.
############
# anoblink # Clear blink bit of current color
############
Declaration: char *anoblink() macro-> calls acolor
Remark: Returns an optimized ANSI string that will turn blink off, only the
blink bit (8) of acurattr is updated.
###############
# aresetcolor # Sets color to reset color, White on Black (7)
###############
Declaration: char *aresetcolor() macro-> calls acolor
Remark: Returns an optimized ANSI string that will reset the current color to
lightgray on black*, acurattr is set to 7.
Discrepancy of QModem:
┌──────────────┬──────┬──────────┬───┬──────────┬───┐
│Color Function│Interp│Foreground│HiL│Background│Blk│
├──────────────┼──────┼──────────┼───┼──────────┼───┤
│*Reset │OTHERS│ ltgray 7 │off│ black 0 │off│
│ ESC[0m │QMODEM│(default) │(d)│(default) │off│ ashortcuts |= !aRESET
│or ESC[m │QMODEM│ ltgray 7 │off│ black 0 │off│ ashortcuts |= aRESET
└──────────────┴──────┴──────────┴───┴──────────┴───┘
- QModem uses the default screen text variable found in the options menu to
define the Reset color. If Strict Color (Video|Toggle) is set to ON, then
Reset color behaves normally.
----------------
The color functions below are not well standardized by ANSI emulators,
therefore their use is not recommended unless necessary. They are not included
in acolor optimizations. YOU MUST update acurattr to reflect the new color
manually.
Some of the color result possibilities are listed below in the windows.
Six emulators have been tested. Assume the most recent versions of each. You
may have to test others if they are not listed. Only boxes with values change.
Those left empty do not.
##############
# aunderline # Set current color to a color defined by underline command
##############
Declaration: char *aunderline(equation) macro-> calls acmd
Remark: Returns an ANSI string that will change to underline color, acurattr
must be updated manually. Equation is designed for this purpose. Use equation
in the form: acurattr=xxx where xxx is the value you expect acurattr will
result. If you leave equation blank, make sure to update acurattr on a
separate line. You MUST update acurattr or you could get unexpected colors.
┌──────────────┬──────┬──────────┬───┬──────────┬───┐
│Color Function│Interp│Foreground│HiL│Background│Blk│
├──────────────┼──────┼──────────┼───┼──────────┼───┤
│ │ANSI │ blue 1 │ │ │ │
│ Underline │NANSI │ blue 1 │ │ │ │
│ │FANSI │ │ │ │ │ none
│ ESC[4m │QMODEM│ ltgray 7 │off│ │off│
│ │PCPLUS│ blue 1 │ │ black 0 │ │ **
│ │TELIX │ │ │ │ │ none
└──────────────┴──────┴──────────┴───┴──────────┴───┘
- Blue is normally the underline color for monochrome systems.
- Procomm Plus has an option that will show actual underlined characters on
EGA/VGA systems. To turn underline off, a reset color needs to be sent.
Example:
aunderline(acurattr=(acurattr&248)|1); // True for ANSI, NANSI
// This will set acurattr=(acurattr&240)|1. This changes the foreground
// to blue (1) only and all other color bits same.
############
# areverse # Set current color to a color defined by reverse command
############
Declaration: char *areverse(equation) macro-> calls acmd
Remark: Returns an ANSI string that will change to the reverse color, acurattr
must be updated manually. Equation is designed for this purpose. Use equation
in the form: acurattr=xxx where xxx is the value you expect acurattr will
result. If you leave equation blank, make sure to update acurattr on a
separate line. You MUST update acurattr or you could get unexpected colors.
┌──────────────┬──────┬──────────┬───┬──────────┬───┐
│Color Function│Interp│Foreground│HiL│Background│Blk│
├──────────────┼──────┼──────────┼───┼──────────┼───┤
│ │ANSI │ black 0 │ │ ltgray 7 │ │
│ Reverse │NANSI │(backgrnd)│ │(foregrnd)│ │ **
│ │FANSI │(backgrnd)│ │(foregrnd)│ │ **
│ ESC[7m │QMODEM│ black 0 │off│ ltgray 7 │off│
│ │PCPLUS│ black 0 │ │ ltgray 7 │ │
│ │TELIX │ black 0 │off│ ltgray 7 │ │
└──────────────┴──────┴──────────┴───┴──────────┴───┘
- NANSI and FANSI swap the foreground and background colors only.
Example:
areverse(acurattr=ATTR(BLACK, LIGHTGRAY)); // True for QMODEM
// This will set acurattr=112. This changes the color to black on
// lightgray, highlight and blink are off.
##############
# ainvisible # Set current color to a color defined by invisible command
##############
Declaration: char *ainvisible(equation) macro-> calls acmd
Remark: Returns an ANSI string that will change to the invisible color,
acurattr must be updated manually. Equation is designed for this purpose. Use
equation in the form: acurattr=xxx where xxx is the value you expect acurattr
will result. If you leave equation blank, make sure to update acurattr on a
separate line. You MUST update acurattr or you could get unexpected colors.
┌──────────────┬──────┬──────────┬───┬──────────┬───┐
│Color Function│Interp│Foreground│HiL│Background│Blk│
├──────────────┼──────┼──────────┼───┼──────────┼───┤
│ │ANSI │ black 0 │on │ black 0 │ │
│ Invisible │NANSI │(backgrnd)│ │ │ │ **
│ │FANSI │(backgrnd)│off│ │ │ **
│ ESC[8m │QMODEM│ ltgray 7 │on │ black 0 │off│
│ │PCPLUS│(dflt bkg)│ │(dflt bkg)│ │ **
│ │TELIX │(backgrnd)│ │ │ │
└──────────────┴──────┴──────────┴───┴──────────┴───┘
- NANSI and FANSI set the foreground color always equal to the background
color until a reset or a cancel invisible (28) is sent. Ie, if you change
the background color, the foreground will change to the same color.
- Procomm Plus sets both the foreground and background colors to the
default terminal background color as found in the options menu.
Example:
ainvisible(acurattr=DARKGRAY|(acurattr&BLINK)); // True for ANSI
// This will set acurattr=8+(current blink bit). This changes the color
// to darkgray on black, blink is unchanged.
################
# anoinvisible # Turn invisible off, for NANSI and FANSI
################
Declaration: char *anoinvisible(equation) macro-> calls acmd
Remark: Returns an ANSI string that will turn off the invisible color,
acurattr must be updated manually. Equation is designed for this purpose. Use
equation in the form: acurattr=xxx where xxx is the value you expect acurattr
will result. If you leave equation blank, make sure to update acurattr on a
separate line. You MUST update acurattr or you could get unexpected colors.
This function is for NANSI and FANSI only because they cancel the foreground
color altogether. See Invisible chart notes above.
*LOCATION FUNCTIONS*
The location functions define 2 char variables. They are axpos and aypos.
These variables must be updated to reflect the current cursor locations on the
screen before any of the location functions are executed. This is not
automatically done since none of the output functions are internal. If you are
writing your own output functions, include calculations that tell define the
current cursor coordinates.
Note also that none of the location functions below do any bounds
checking. Ie, do not pass values for axpos or aypos that are beyond the
dimensions of the screen. Most ANSI emulators tend to have built in boundary
checking so the cursor will not go beyond screen coordinates, but OptANSI does
not check current values of axpos or aypos. If there is every any doubt at any
point in your program where bounds might have been exceeded, use aupdatexy()
functions to reevaluate axpos and aypos.
###########
# agotoxy # Locate the cursor to new x and y location
###########
Declaration: char *agotoxy(char x, char y) function
Remark: Returns an optimized ANSI string that will place the cursor at the
desired location on the screen, updates axpos and aypos. Equivalent to conio's
gotoxy() function.
################
# aforcegotoxy # Forces locate of the cursor to x and y ignoring optimizations
################
Declaration: char *aforcegotoxy(char x, char y) macro-> calls agotoxy
Remark: Returns a full ANSI string that will place the cursor at the desired
location on the screen, updating axpos and ypos. This function is like agotoxy
except that it will send the complete ANSI string as if the cursor location
was reinitialized, ie it ignores the previous axpos and aypos values when
returning the new location. For instance, lets say that you are worried about
line noise through the modem and axpos or aypos possibly become obscured,
aforcegotoxy(1, 1) would ensure that x and y equal 1 by ignoring internal
optimizations.
#########
# adown # Move the cursor down y positions
#########
Declaration: char *adown(char y) function
Remark: Returns an optimized ANSI string that will move the cursor down y
positions.
#######
# aup # Move the cursor up y positions
#######
Declaration: char *aup(char y) macro-> calls acmd
Remark: Returns an optimized ANSI string that will move the cursor up y
positions.
##########
# aright # Move the cursor right x positions
##########
Declaration: char *aright(char x) macro-> calls acmd
Remark: Returns an ANSI string that will move the cursor right x positions.
#########
# aleft # Move the cursor left x positions
#########
Declaration: char *aleft(char x) macro-> calls acmd
Remark: Returns an optimized ANSI string that will move the cursor left x
positions.
#########
# ahome # Move cursor to top left corner of screen: 1, 1
#########
Declaration: char *ahome() macro-> calls agotoxy
Remark: Returns an optimized ANSI string that will home the cursor to the top
left cursor position, axpos=1 and aypos=1.
###############
# asavecursor # Save current cursor position
###############
Declaration: char *asavecursor() function
Remark: Returns an optimized ANSI string that will save the current cursor
position. arestorecursor will restore the cursor back to this saved position.
NOTE: asavecursor does not nest. It can only store one cursor position.
##################
# arestorecursor # Restore cursor position to saved
##################
Declaration: char *arestorecursor() function
Remark: Returns an optimized ANSI string that will return the cursor to the
last position saved by asavecursor. If no position was last saved by
asavecursor, then the cursor will not relocate. Some ANSI implementations
assume position 1,1 for prestored location.
Example:
agotoxy(5, 5); // Locate to position 5, 5
asavecursor() // Saves 5, 5
agotoxy(1, 1); // Locates to 1, 1
arestorecursor(); // Returns cursor to 5, 5
############
# awherexy # Interpret x and y cursor locations from atest result string
############
Declaration: unsigned awherexy(char *s) function
Remark: This function is very similar to aresult() and can be used in the same
way, probably doing a better job. The atest response string has the cursor x
and y locations. awherexy() will extract this information into an x and y
cursor location. aresult() doesn't extract this information. awherexy()
returns an unsigned integer whose most significant byte is the x location and
the least significant byte is the y location. The awherexy() function should
follow atest().
Example:
char s[15];
unsigned i;
atest(); // asks ANSI for cursor location
readbuf(&s); // reads input buffer until enter
i=awherexy(s);
axpos=i >> 8; // MSB
aypos=i & 256; // LSB
NOTE: Another use for awherexy that is not otherwise obvious is the ability to
extract screen dimensions. It works because ANSI emulators have boundary
constraining, such that if you put agotoxy(99, 99); before the above example
fragment above, it will locate the cursor to position 99, 99 or the screen
boundaries whichever comes first. You can then use awherexy() to extract the
current position and therefore the bounds. For instance, if the screen
dimensions are 80x25, 80,25 will be returned.
*OTHER FUNCTIONS*
The miscellaneous functions below are only available locally on a DOS
machine. Most telecommunications programs do not support them. These commands
are discouraged from use because they can effect the way the keyboard behaves
and change modes that make many ANSI functions inactive or misbehave. However,
because ANSI implements them, they are supported by OptANSI as well. They can
be very useful functions to very specific applications.
#############
# akeyboard # Reassign keyboard keys
#############
Declaration: char *akeyboard(int key, char *str, char *buf)
function
Remark: Returns an ANSI string that will redefine keys on your keyboard, like
a macro. For instance, if you send the key ALT1 to be reassigned to the macro
"I use OptANSI!", every time you hit ALT1 from DOS, that macro will display.
A separate buffer is needed by this function because the global buffer space
may be too small for str. Define this buffer space in your program and point
buf to it. The parameter key is the input key you wish to define. To use
special keys like the function keys, arrows, or ALT-combinations, use the SKEY
macro defined below. For redefining one letter keys or control sequences like
CTRL-A, use that character value (CTRL-A is 1). If you want to make
complicated command sequences similar a batch language, you must include all
newline chars as well. For instance, to do a dir followed by a pause, use:
char buf[256];
akeyboard(SKEY(ALT1), "DIR /w\nPAUSE\n", &buf);
SKEY (below) expands ALT1 which is defined in SKEYS.H for use with
akeyboard(). The parameter buf is used to point to new buffer. It needs to be
large enough to accept all characters you define in str + 11.
########
# SKEY # Calculates value for special keys for use in parameter for akeyboard
########
Declaration: int SKEY(char key) macro-> 0,key
Remark: This macro is necessary to expand special keys like Function keys,
arrows, all ALT combinations, and other combinations of the above into a
parameter which can be used by akeyboard (defined above). Make sure to include
the header file SKEYS.H which defines most of the definable special keys.
These macros are listed below:
UP, DOWN, LEFT, RIGHT, PGUP, PGDOWN, HOME, END
CTRLLEFT, CTRLRIGHT, CTRLPGUP, CTRLPGDOWN, CTRLHOME, CTRLEND
F1 - F10, CTRLF1 - CTRLF10, SHFTF1 - SHFTF10, ALTF1 - ALTF10
ALTA - ALTZ, ALT0 - ALT9
#########
# amode # Function for use with asetmode and aresetmode
#########
Declaration: char *amode(int mode, char cmd) function
Remark: See asetmode and aresetmode for more details.
############
# asetmode # Sets mode to an ANSI defined mode or changes display rules
############
Declaration: char *asetmode(int mode) macro-> calls amode
Remark: This function returns an ANSI string that changes the current video
mode or sets an ANSI variable to on/true. Set mode to a value listed below.
NOTE also that changing to another mode may relocate the cursor and/or change
the color. The global variables axpos, aypos, and acurattr must be updated
manually.
Macros, Mode Values, and their result of usage:
BW40 0 Text 40x25, 16 colors (ANSI colors override B&W modes)
C40 1 Text 40x25, 16 colors
BW80 2 Text 80x25, 16 colors (ANSI colors override B&W modes)
C80 3 Text 80x25, 16 colors
G320_200 4 Graphics 320x200, 4 colors
G320_200GR 5 Graphics 320x200, 4 grey colors
G640_200BW 6 Graphics 640x200, 2 colors - black & white
aCURSORWRAP 7 -- Cursor wrap on/off
G320_200V 13 Graphics 320x200, 16 colors, (VGA)
G640_200V 14 Graphics 640x200, 16 colors, (VGA)
G640_350V 16 Graphics 640x350, 16 colors, (VGA)
G640_480BWV 17 Graphics 640x480, 2 colors - black & white, (VGA)
G640_480V 18 Graphics 640x480, 16 colors, (VGA)
G300_200V 19 Graphics 300x200, 256 colors, (VGA)
ROWS43 43 43 line mode in modes 0-3 (EGA, NANSI extension)
ROWS50 50 50 line mode in modes 0-3 (VGA, NANSI extension)
aBIOSTTY 97 -- ANSI BIOS/WRITE_TTY (NANSI extension)
aFASTSCROLL 98 -- FAST SCROLL on/off (NANSI extension)
aGRAPHICSCURSOR 99-- Graphics cursor on/off (NANSI extension)
n Other mode not listed above (NANSI extension)
VGA modes are supported by ANSI versions DOS 4.0 and above. Mode values do not
necessarily match BIOS values.
NOTE: On/Off switches like Cursor wrap on/off are set on with asetmode and
turned off with aresetmode (below). So to turn cursor wrap on you'd use
asetmode(aCURSORWRAP). To turn it off you'd use aresetmode(aCURSORWRAP).
You may use the macros defined in OPTANSI.H: aCURSORWRAP, aBIOS, aWRITE_TTY,
aBIOSTTY, aFASTSCROLL, and aGRAPHICSCURSOR.
##############
# aresetmode # Resets mode to an ANSI defined mode or changes display rules
##############
Declaration: char *aresetmode(int mode) macro-> calls amode
Remark: This function returns an ANSI string that changes the current video
mode or sets an ANSI variable to off/false. Set mode to a value listed in
asetmode above. NOTE also that changing to another mode may relocate the
cursor and/or change the color. The global variables axpos, aypos, and
acurattr must be updated manually.
NOTE: As far as changing video modes, there may or may not be a difference
between asetmode and aresetmode. This is dependant on the ANSI driver. I have
not noticed any differences with the tests that I've run.
#############
# atextmode # Switch to a text mode, though really the same as asetmode
#############
Declaration: char *atextmode(int mode) macro-> calls asetmode
Remark: This is a macro equivalent to conio's textmode. You can use conio's
BW40, C40, BW80, and C80 macros, but any others have different effects. This
function is the same thing as asetmode.
###############
# acursorwrap # Turn on cursorwrap
###############
Declaration: char *acursorwrap() macro-> calls asetmode
Remark: This function will return an ANSI string that will turn on cursor
wrap.
#################
# anocursorwrap # Turn off cursorwrap
#################
Declaration: char *anocursorwrap() macro-> calls aresetmode
Remark: This function will return an ANSI string that will turn off cursor
wrap.
*COMPILATION NOTES*
If you are a registered user of the OptANSI library, you will be able to
compile your own versions of the code.
Take special caution when modifying AGOTOXY.C and ACOLOR.C because much
of the code is combined meta or inline assembly. These and some of the other
functions use registers in place of variables for faster and tighter
execution. This practice is safe with BC++ as long as you use instructions
that do not rely on the selected registers. To ensure safe compilation on
these files, you can use your debugger or compile your code to assembly to
examine it.
When compiling there are some special definitions you can set in
OPTANSI.H to include certain compilations. They are located at the top of
OPTANSI.H and are only defined for OptANSI functions. They are listed below:
NANSI
If #define NANSI is 1 in OPTANSI.H during compilation, special NANSI
optimizations which are not otherwise included will be included. This will add
another 120 bytes of code. This macro definition is different than the aNANSI
flag because NANSI specifies whether you want NANSI (and FANSI) support code
included at all, whereas the aNANSI flag determines during execution whether
the option is available. aNANSI has no effect without NANSI being true. Note:
acolor will try to use special NANSI output to turn off highlight and blink if
ashortcuts has the aNANSI flag on and NANSI support is compiled in, so make
sure that you check for NANSI presence before setting the aNANSI flag. You can
do this by either asking the user or sending a NANSI only command and then
testing the status literally.
SIZE
If #define SIZE is 1 in OPTANSI.H during compilation, the C preprocessor
will compile aspects of the code that are more likely to produce smaller code
by calling functions instead of multi-purpose macros. This is done at the cost
of speed so define SIZE to 0 for faster code. NOTE: This option was removed
until further tests could be performed. It is defined for future use.
REGISTERED
If #define REGISTER is 1 in OPTANSI.H during compilation, all excess demo
code will be eliminated for registered version and tightened code.
There are also other macros defined in OPTANSI.H that may be useful to
your implementation. For instance if you are using C++, you can use EXTERN in
place of extern. This will use extern "C" so that you can use standard C
functions as with OptANSI.
------------------------------------------------------------------------------
AOPT is a trademark or copyright of Michael Dannov
ANSI.SYS is a trademark or copyright of Microsoft Corp.
NANSI.SYS is a trademark or copyright of Daniel Kegal.
FCONSOLE.DEV and FANSI-CONSOLE are trademarks or copyright of Hersey Micro
Consulting, Inc.
Procomm Plus is a trademark or copyright of DataStorm Technologies, Inc.
QMODEM is a trademark or copyright of Mustang Software, Inc.
TELIX is a trademark or copyright of Exis Inc and Colin Sampaleanu